package com.dys.designpattern.singleton;

import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: 疾风
 * @ClassName: ContainerSingleton
 * @Description: 7.单例模式-容器单例(适用于创建多个实例的场景)
 * @CreateDate: 2024/05/11
 * @Version: v1.0.0
 */
public class ContainerSingleton {

    /**
     * 1.私有化构造器,防止外部实例化
     */
    private ContainerSingleton() {
    }

    /**
     * 2.私有静态变量，用于保存单例实例
     */
    private static final Map<String, Object> INSTANCE = new ConcurrentHashMap<String, Object>();

    /**
     * 3.提供全局访问点,供外部调用
     *
     * @param className 用户传递的类
     * @return 容器中的实例
     */
    public static Object getBean(String className) {
        synchronized (INSTANCE) {
            if (!INSTANCE.containsKey(className)) {
                Object obj = null;
                try {
                    // 使用反射创建实例(不能获取私有构造器的类)
                    // obj = Class.forName(className).newInstance();
                    // 使用反射创建实例(能获取私有构造器的类)
                    Class<?> clazz = Class.forName(className);
                    Constructor<?> constructor = clazz.getDeclaredConstructor();
                    // 即便传递的bean构造器私有化了，也可以获取到
                    constructor.setAccessible(true);
                    obj = constructor.newInstance();
                    // 将创建的容器放到实例中
                    INSTANCE.put(className, obj);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return obj;
            } else {
                return INSTANCE.get(className);
            }
        }
    }
}
